#include "Parser.h"
#include "Lex.h"

Parser::Parser()
	: lex()
{
}


Parser::~Parser()
{
}

// read nextoken, return true if reaching file end
void Parser::nextToken()
{
	lex.nextToken();
}

// Parse a list and produce a binary tree recursively
ParserTree* Parser::parseList()
{
	ParserTree* tree = NULL;
	ParserTreeNode* traverse;
	ParserTree* child;

	switch (lex.currentToken.type)
	{
	case END:
		break;

	case LEFT_PARENT:
	{
		tree = new ParserTree();
		traverse = tree;

		bool completed = false;
		while (lex.currentToken.type != END)
		{	
			lex.nextToken();

			switch(lex.currentToken.type)
			{
			case DOT:			//	another list member seperated by a dot, write it to right child 
				if (traverse->getChild(false))
				{
					std::cout << "ERROR: more than three elements connected by DOT!\n";
					exit(1);
				}

				lex.nextToken();
				child = this->parseList();
				if (!child)
				{
					std::cout << "ERROR: Nothing following the DOT !\n";
					exit(1);
				}
				else
				{
					if (!traverse->getChild(true))
					{
						std::cout << "ERROR: DOT preceded by nothing ! !\n";
						exit(1);
					}
					traverse->addChild(false, child);
				}
				break;
			case LEFT_PARENT:
			case LITERAL:
			case NUMBER:			//	another list member seperated by spaces, create right child and divide it 
				if (traverse->getChild(true) && traverse->getChild(false))
				{
					//	the tree has both left and right child, error
					std::cout << "ERROR: more than three elements connected by DOT !\n";
					exit(1);
				}
				if (traverse->getChild(true))
				{
					//	if left child occupied, turn to the right child
					traverse = traverse->addChild(false, new ParserTree());
					child = this->parseList();
					traverse->addChild(true, child);
				}
				else
				{
					child = this->parseList();
					traverse->addChild(true, child);
				}
				break;
			case RIGHT_PARENT:
				completed = true;
				break;
			case ERROR:
				std::cout << "ERROR: invalid token '" << lex.currentToken.str.c_str() << "'!\n";
				exit(1);
				break;
			}
			if (completed)
				break;
		}
		if (!completed)
		{
			std::cout << "ERROR: parenthsis unmatched !" << "\n";
			exit(1);
		}
		break;
	}

	case RIGHT_PARENT:
		std::cout << "ERROR: Unmatched ')' !\n";
		exit(1);
		break;
	case LITERAL:
		tree = new ParserTreeNode(lex.currentToken.str);
		break;
	case NUMBER:
		tree = new ParserTreeNode(lex.currentToken.number);
		break;
	case DOT:
		std::cout << "ERROR: DOT preceded by nothing !\n";
		exit(1);
		break;
	case ERROR:
		std::cout << "ERROR: invalid token '" << lex.currentToken.str.c_str() << "'!\n";
		exit(1);
		break;

	default:
		;
	}

	return tree;
}

bool Parser::isFileEnd()
{
	return lex.currentToken.type == END;
}
